package zhou.chs.p8_1;

import android.graphics.Color;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.Hashtable;
import java.util.Timer;
import java.util.TimerTask;
import weiqian.hardware.SerialPort;
import weiqian.hardware.CustomFunctions;
public class MainActivity extends AppCompatActivity {
    int hmax=13;       //回路数量
    //回路名称
    String[] hname = {"三污6KV I段进线84601","三污6KV II段进线84602","三污6KV 母联84603",
            "1#变压器84607", "2#变压器84608", "1#鼓风机84611", "3#鼓风机84613",
            "4#鼓风机84614", "5#鼓风机84615", "6#鼓风机84616", "2#排水泵84617",
            "3#排水泵84618", "7#鼓风机84619"};
    //声明控件
    TextView tvSta;     //显示运行记录
    TextView tvd;       //显示日期时间
    TextView[] U = new TextView[9];         //显示系统电压
    TextView[] IA = new TextView[hmax];     //显示回路电流
    TextView[] HL = new TextView[hmax];     //显示回路编号
    TextView[] XX = new TextView[14];       //显示小电流接地选线状态
    TextView[] ZL = new TextView[5];        //显示直流电源运行参数
    TextView[] DB = new TextView[24];       //显示电度表底数
    LinearLayout ll1,ll2;
    //声明变量
    SerialPort serialPort,serialPort2;   //串口1和串口2
    private ReadThread1 mReadThread1;	//串口1读取线程
    private ReadThread2 mReadThread2;	//串口2读取线程
    Hashtable mtable;          //哈希表，保存已接入客户端IP地址和Socket
    Hashtable adrtable;        //哈希表，保存回路序号与IP末位地址的对应关系
    OutputStream out;           //以太网输出数据流
    Handler mHandler; 		    //消息线程
    Socket mSocket;  		    //网络Socket
    StartThread st;     		//TCP客户端线程
    RecThread rt; 	            //TCP数据接收线程
    String strSta = "";    	//运行记录文本
    byte[] rbuf1 = new byte[32];    //COM1接收缓冲区
    byte[] rbuf2 = new byte[32];    //COM2接收缓冲区
    byte rbuf[] = new byte[2048]; //以太网接收缓冲区
    byte buf[] = new byte[256]; 	//以太网报文解析缓冲区
    int bw; //报文组数
    byte[] tbuf = {(byte)0x90,(byte)0xEB,(byte)0x1F,(byte)0x00,(byte)0x00,(byte)0x00,
            (byte)0x90,(byte)0xEB,(byte)0x00,(byte)0x00,(byte)0x0A,(byte)0x00,
            (byte)0x00,(byte)0x00,(byte)0x43,(byte)0x00,(byte)0x00,(byte)0x00,
            (byte)0x01,(byte)0x00,(byte)0x10,(byte)0x00,(byte)0x00,(byte)0x00,
            (byte)0x00,(byte)0x00,(byte)0x90,(byte)0xEB,        //APCI
            (byte)0x15,(byte)0x81,(byte)0x2A,(byte)0x43,(byte)0xFE,(byte)0xF1,
            (byte)0x09,(byte)0x01,(byte)0x02,(byte)0x00,(byte)0x01 };    //以太网发送缓冲区
    boolean running = false;
    int len;    	//以太网接收数据长度
    //电度表表号
    byte[] mymt = {(byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,    //84601
        (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84602
        (byte)0x07, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84607
        (byte)0x08, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84608
        (byte)0x11, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,    //84611
        (byte)0x13, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84613
        (byte)0x14, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84614
        (byte)0x15, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84615
        (byte)0x16, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84616
        (byte)0x17, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84617
        (byte)0x18, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84618
        (byte)0x19, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,     //84619
        (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00};     //84603
    
    int tn=100,tn2=0;  //定时计数
    int[] bn = new int[hmax];   // 发送报文计数
    //回路IP地址
    String[] pcsip ={"198.121.0.61","198.121.0.62","198.121.0.63","198.121.0.67",
            "198.121.0.68","198.121.0.71","198.121.0.73","198.121.0.74",
            "198.121.0.75","198.121.0.76","198.121.0.77","198.121.0.78",
            "198.121.0.79"};
    String strip;
    int[] Sta = new int[hmax];      // 状态：0-未连接  1-已连接
    int[] sn = new int[hmax];       // 连接计数
    byte[][] Reg6 = new byte[hmax][64];     //遥测寄存器，每个回路16个遥测量，64字节
    byte[][] Reg2 = new byte[hmax][4];      //继电保护动作寄存器，每个回路4字节
    byte[][] Reg3 = new byte[hmax][4];      //报警寄存器，每个回路4字节
    byte[][] Reg5 = new byte[hmax][4];      //遥信寄存器，每个回路4字节
    byte[] Reg = new byte[20+hmax*8];      //小电流预留10字节，直流10字节，其余电度表，每个回路8字节
    String mdate,mtime;  //当前日期和时间
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        CustomFunctions.FullScreenSticky(getWindow()); //全屏模式
        ll1 = findViewById(R.id.idll1);
        ll2 = findViewById(R.id.idll2);
        tvSta = findViewById(R.id.idtv);
        tvd = findViewById(R.id.idtvt);
        //系统电压显示控件数组
        int[] idu = {R.id.idtv11,R.id.idtv12,R.id.idtv13,
                R.id.idtv21,R.id.idtv22,R.id.idtv23,
                R.id.idtv31,R.id.idtv32,R.id.idtv33};
        for(int i=0;i<9;i++){
            U[i]=findViewById(idu[i]);
        }
        //回路电流显示控件数组
        int[] idx = {R.id.idl1,R.id.idl2,R.id.idl3,R.id.idl4,R.id.idl5,R.id.idl6,R.id.idl7,
                R.id.idl8,R.id.idl9,R.id.idl10,R.id.idl11,R.id.idl12,R.id.idl13,R.id.idl14};
        for(int i=0;i<14;i++){
            XX[i]=findViewById(idx[i]);
        }
        //电度表底数显示控件数组
        int[] iddb = {R.id.idd1,R.id.idd2,R.id.idd3,R.id.idd4,R.id.idd5,R.id.idd6,
                R.id.idd7,R.id.idd8,R.id.idd9,R.id.idd10,R.id.idd11,R.id.idd12,
                R.id.idd13,R.id.idd14,R.id.idd15,R.id.idd16,R.id.idd17,R.id.idd18,
                R.id.idd19,R.id.idd20,R.id.idd21,R.id.idd22,R.id.idd23,R.id.idd24,};
        for(int i=0;i<24;i++){
            DB[i]=findViewById(iddb[i]);
        }
        //直流电源运行数据显示控件数组
        int[] idz = {R.id.idz1,R.id.idz2,R.id.idz3,R.id.idz4,R.id.idz5};
        for(int i=0;i<5;i++){
            ZL[i]=findViewById(idz[i]);
        }
        //回路编号和电流显示控件数组
        int[] idhl = {R.id.idtv012,R.id.idtv022,R.id.idtv032,R.id.idtv072,
                R.id.idtv082,R.id.idtv112,R.id.idtv132,R.id.idtv142,R.id.idtv152,
                R.id.idtv162,R.id.idtv172,R.id.idtv182,R.id.idtv192};
        int[] idia = {R.id.idtv013,R.id.idtv023,R.id.idtv033,R.id.idtv073,
                R.id.idtv083,R.id.idtv113,R.id.idtv133,R.id.idtv143,R.id.idtv153,
                R.id.idtv163,R.id.idtv173,R.id.idtv183,R.id.idtv193};
        for(int i=0;i<hmax;i++){
            HL[i]=findViewById(idhl[i]);
            IA[i]=findViewById(idia[i]);
        }
        //运行记录可滚动显示
        tvSta.setMovementMethod(ScrollingMovementMethod.getInstance());
        mtable=new Hashtable();     //初始化哈希表
        adrtable=new Hashtable();
        for (int i=0;i<hmax;i++) {
            String s = pcsip[i];
            String[] ips = s.split("\\.");
            int n = Integer.parseInt(ips[3]);   //分解出IP末位地址
            adrtable.put(n,i);                  //新的IP地址加入列表
        }
        mHandler = new MyHandler();		//实例化Handler，用于进程间的通信
        serialPort = new SerialPort();  //串口1
        serialPort2 = new SerialPort(); //串口2
        //打开2个串口
        serialPort.open("COM1",9600, 8, "N", 1);
        serialPort2.open("COM2",1200, 8, "E", 1);
        mReadThread1 = new ReadThread1();
        mReadThread1.start();    //启动串口1接收数据线程
        mReadThread2 = new ReadThread2();
        mReadThread2.start();   //启动串口2接收数据线程
        Timer mTimer = new Timer();   	//新建Timer
        mTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                Message msg = mHandler.obtainMessage();   //创建消息
                msg.what = 0;                      	//变量what赋值
                mHandler.sendMessage(msg);     	//发送消息
            }
        }, 2000, 1000);     //延时2000ms，然后每隔1000ms发送消息
        for(int i=0;i<hmax;i++) Sta[i]=0;  //状态值初始化
    }
    // 定义byte[]转float方法
    public static float B2F(byte[] a) {
        int c = (a[0]<<24)|((a[1]&0xFF)<<16)|((a[2]&0xFF)<<8)|(a[3]&0xFF);
        return Float.intBitsToFloat(c);
    }
    //界面切换按钮响应
    public void sw(View view){
        if(ll1.getVisibility()==View.VISIBLE){
            ll1.setVisibility(View.INVISIBLE);
            ll2.setVisibility(View.VISIBLE);
        }else {
            ll1.setVisibility(View.VISIBLE);
            ll2.setVisibility(View.INVISIBLE);
        }
    }
    //在主线程处理Handler传回来的message
    class  MyHandler extends Handler{
        @Override
        public void handleMessage(Message msg) {
            switch (msg.what) {
                case 0: //定时时间到
                    Date now = new Date();
                    mtime = String.format("%tT",now);
                    mdate = String.format("%tF",now);
                    tvd.setText(mdate + "  " + mtime);  //显示当前日期和时间
                    //读取电度表数据
                    tn2++;
                    if(tn2>=hmax*2)tn2=0;
                    if(tn2<hmax){
                        DLT645((tn2),0x9010);	  //有功电量
                    }else {
                        DLT645((tn2-hmax),0x9110);	//无功电量
                    }
                    //读取直流电源和小电流接地选线装置数据
                    if(tn2%2==1){
                        byte[] tbuf1={(byte)0x05,(byte)0x03,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x05,
                                (byte)0x84,(byte)0x4D};
                        serialPort.write(tbuf1,8); //发送tbuf1中前8个字节数据
                    }else{
                        byte[] tbuf1={(byte)0x14,(byte)0x02,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x13,
                                (byte)0x3B,(byte)0x02};
                        serialPort.write(tbuf1,8); //发送tbuf1中前8个字节数据
                    }
                    //以太网
                    tn++;
                    if(tn>=hmax) tn=0;
                    for(int i=0;i<hmax;i++){
                        sn[i]++;
                        if(sn[i]>120) Sta[i]=0;     //120秒内收不到数据，判断为网络中断
                    }
                    if(Sta[tn]==0) {
                        strip=pcsip[tn];
                        st=new StartThread();
                        st.start();     //网络未连接或中断，重新建立连接
                    }else{
                        try {           //网络正常则发送报文
                            String s = pcsip[tn];
                            Socket ss = (Socket) mtable.get(s);
                            out = ss.getOutputStream();     //获取客户端对应的socket并建立数据流
                            tbuf[10] = (byte) 0x0A;         //本机IP末位
                            String[] ips = s.split("\\.");
                            int n = Integer.parseInt(ips[3]); //分解出IP末位地址
                            tbuf[14] = (byte) (n & 0xFF);
                            tbuf[16] = (byte) (bn[tn] & 0xFF);  //报文计数
                            tbuf[17] = (byte) ((bn[tn] >> 8) & 0xFF);
                            tbuf[31] = tbuf[14];
                            tbuf[34] = tbuf[16];
                            tbuf[2] = (byte) 0x1F;
                            tbuf[30] = (byte) 0x2A;
                            tbuf[33] = (byte) 0xF4;
                            tbuf[36] = (byte) 0x05;
                            tbuf[37] = (byte) 0x01;
                            out.write(tbuf, 0, 39);   //发送数据，读开关状态，兼心跳包
                            bn[tn]++;
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                    //显示回路数据
                    byte[] a = new byte[4];
                    for(int i=0;i<hmax;i++){
                        for(int j=0;j<4;j++) a[3-j] = Reg6[i][j];
                        float f=B2F(a);
                        //显示回路电流
                        IA[i].setText(String.format("I=%.1fA",f));
                        //显示开关状态，红色为合位，绿色为断位
                        if((Reg5[i][0]&0x01)==(byte)0x01) HL[i].setBackgroundColor(Color.RED);
                        else HL[i].setBackgroundColor(Color.GREEN);
                    }
                    //显示系统电压
                    for(int j=0;j<4;j++) a[3-j] = Reg6[0][16+j];
                    float f=B2F(a);
                    U[0].setText(String.format("Ua1=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[0][20+j];
                    f=B2F(a);
                    U[1].setText(String.format("Ub1=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[0][24+j];
                    f=B2F(a);
                    U[2].setText(String.format("Uc1=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[1][16+j];
                    f=B2F(a);
                    U[3].setText(String.format("Ua2=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[1][20+j];
                    f=B2F(a);
                    U[4].setText(String.format("Ub2=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[1][24+j];
                    f=B2F(a);
                    U[5].setText(String.format("Uc2=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[0][28+j];
                    f=B2F(a);
                    U[6].setText(String.format("Uab=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[0][32+j];
                    f=B2F(a);
                    U[7].setText(String.format("Ubc=%.2fkV",f));
                    for(int j=0;j<4;j++) a[3-j] = Reg6[0][36+j];
                    f=B2F(a);
                    U[8].setText(String.format("Uca=%.2fkV",f));
                    //小电流报警显示
                    int m1 = Reg[0]&0xFF;
                    int m2 = Reg[2]&0xFF;
                    for(int i=0;i<7;i++){
                        if((m1&0x01)==1) XX[i].setBackgroundColor(Color.RED);
                        else XX[i].setBackgroundColor(Color.GREEN);
                        if((m2&0x01)==1) XX[i+7].setBackgroundColor(Color.RED);
                        else XX[i+7].setBackgroundColor(Color.GREEN);
                        m1>>=1;
                        m2>>=1;
                    }
                    //直流电源显示
                    for(int i=0;i<5;i++){
                        int m = ((Reg[2*i+10]&0xFF)<<8)|((Reg[2*i+11]&0xFF));
                        ZL[i].setText(String.format("%.1f",(float)m/10));
                    }
                    //电度表底数显示
                    for(int i=0;i<24;i++){
                        String dbs = String.format("%02X",Reg[4*i+20]&0xFF)+
                                String.format("%02X",Reg[4*i+21]&0xFF)+
                                String.format("%02X",Reg[4*i+22]&0xFF)+
                                String.format(".%02X",Reg[4*i+23]&0xFF);
                        DB[i].setText(String.format("%.2f", Float.valueOf(dbs)));
                    }
                    //运行记录显示
                    String[] ss = strSta.split("\\n");
                    int n = ss.length;  //获取记录数
                    if(n>20){       //只保留最近20条记录
                        strSta="";
                        for(int i=0;i<20;i++) strSta = strSta + ss[i] + "\n";
                    }
                    tvSta.setText(strSta);
                        break;
                case 1: //已建立连接
                    String s=msg.obj.toString();
                    for(int i=0;i<hmax;i++){
                        if(s.equals(pcsip[i])){
                            Sta[i]=1;
                            sn[i]=0;
                        }
                    }
                    strSta=mdate +" " + mtime + " "+s+"已连接\n"+strSta;
                    break;
            }
        }
    }
    //建立socket连接的线程
    private class StartThread extends Thread{
        @Override
        public void run() {
            try {
                mSocket = new Socket(strip, 6000);//连接微机综合保护器
                mtable.put(strip,mSocket);  //新的服务端加入列表
                //启动接收数据的线程
                rt = new RecThread(mSocket);
                rt.start();
                running = true;
                if(mSocket.isConnected()){  //成功连接获取socket对象则发送成功消息
                    Message msg = mHandler.obtainMessage();
                    msg.obj=strip;
                    msg.what=1;
                    mHandler.sendMessage(msg);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    // TCP服务器数据接收线程
    private class RecThread extends Thread {
        private final Socket mmSocket;
        private final InputStream mmInStream;
        public RecThread(Socket socket) {
            mmSocket = socket;
            InputStream tmpIn = null;
            try {
                tmpIn = mmSocket.getInputStream();  //数据通道创建
            } catch (IOException e) { }
            mmInStream = tmpIn;
        }
        public final void run() {
            while (!mmSocket.isClosed()) {
                try {
                    int cnt = mmInStream.read(rbuf);
                    if(cnt>27) {    //数据长度大于27字节为有效数据
                        len=cnt;
                        asdu10();  //报文解析
                    }
                } catch (NullPointerException e) {
                    e.printStackTrace();
                    break;
                } catch (IOException e) {
                    break;
                }
            }
        }
    }
    //以太网报文解析
    public void gin(int addr) {
        if((buf[0]==(byte) 0x0A)&&(buf[1]==(byte) (0x81&0xFF))) {  // ASDU10报文
            int hz = buf[8]&0xFF;        //取得组号
            int hn = buf[7]&0x3F;       //组数
            if (hz == 6) {  //遥测
                for(int i=0;i<hn;i++){
                    int hm = buf[10*i+9];        //取得条目号
                    for (int j = 0; j < 4; j++) {
                        if (hm <= 16)
                            //遥测量为4字节浮点数，低位在前
                            Reg6[addr][4 * (hm - 1) + j] = buf[10 * i + 14+j];
                    }
                }
            }
            if (hz == 2) {  //继电保护
                for(int i=0;i<hn;i++){
                    int m = ((Reg2[addr][2]&0xFF)<<16)|((Reg2[addr][1]&0xFF)<<8)|(Reg2[addr][0]&0xFF);
                    int hm = buf[19*i+9];        //取得条目号
                    if ((buf[19*i+14]&0x03)==(byte)0x02){    //保护动作，对应位置1
                        m = m|(1<<(hm-1));
                        if(hm>1) strSta = mdate +" " + mtime + " " + hname[addr] +"继电保护动作\n"+strSta;
                    }
                    if ((buf[19*i+14]&0x03)==(byte)0x01){    //保护返回，对应位置0
                        m = m&(~(1<<(hm-1)));   //保护返回暂不记录
                    }
                    Reg2[addr][2] = (byte)((m>>16)&0xFF);
                    Reg2[addr][1] = (byte)((m>>8)&0xFF);
                    Reg2[addr][0] = (byte)(m&0xFF);
                }
            }
            if (hz == 3) {  //报警信息
                for(int i=0;i<hn;i++){
                    int m = ((Reg3[addr][3]&0xFF)<<24)|((Reg3[addr][2]&0xFF)<<16)|((Reg3[addr][1]&0xFF)<<8)|(Reg3[addr][0]&0xFF);
                    int hm = buf[15*i+9];        //取得条目号
                    if ((buf[15*i+14]&0x03)==(byte)0x02){    //报警动作，对应位置1
                        m = m|(1<<(hm-1));
                        if(hm==16) strSta = mdate +" " + mtime + " " + hname[addr] +"事故总信号\n"+strSta;
                        if(hm==18) strSta = mdate +" " + mtime + " " + hname[addr] +"PT断线\n"+strSta;
                        if(hm==20) strSta = mdate +" " + mtime + " " + hname[addr] +"控制回路断线\n"+strSta;
                        if(hm==23) strSta = mdate +" " + mtime + " " + hname[addr] +"接地报警\n"+strSta;
                        if(hm==24) strSta = mdate +" " + mtime + " " + hname[addr] +"过负荷报警\n"+strSta;
                    }
                    if ((buf[15*i+14]&0x03)==(byte)0x01){    //报警返回，对应位置0
                        m = m&(~(1<<(hm-1)));   //报警返回暂不记录
                    }
                    Reg3[addr][3] = (byte)((m>>24)&0xFF);
                    Reg3[addr][2] = (byte)((m>>16)&0xFF);
                    Reg3[addr][1] = (byte)((m>>8)&0xFF);
                    Reg3[addr][0] = (byte)(m&0xFF);
                }
            }
            if (hz == 5) {  //遥信
                for(int i=0;i<hn;i++){
                    int m = ((Reg5[addr][3]&0xFF)<<24)|((Reg5[addr][2]&0xFF)<<16)|((Reg5[addr][1]&0xFF)<<8)|(Reg5[addr][0]&0xFF);
                    int hm = buf[15*i+9];        //取得条目号
                    if ((buf[15*i+14]&0x03)==(byte) 0x02){    //遥信变位，对应位置1
                        m = m|(1<<(hm-1));
                        if ((buf[15*i+2]==(byte) 0x01)&&(hm==1)) strSta = mdate +" " + mtime + " " + hname[addr] +"开关合闸\n"+strSta;
                    }
                    if ((buf[15*i+14]&0x03)==(byte) 0x01){    //遥信变位，对应位置0
                        m = m&(~(1<<(hm-1)));
                        if ((buf[15*i+2]==(byte) 0x01)&&(hm==1)) strSta = mdate +" " + mtime + " " + hname[addr] +"开关跳闸\n"+strSta;
                    }
                    Reg5[addr][3] = (byte)((m>>24)&0xFF);
                    Reg5[addr][2] = (byte)((m>>16)&0xFF);
                    Reg5[addr][1] = (byte)((m>>8)&0xFF);
                    Reg5[addr][0] = (byte)(m&0xFF);
                }
            }
        }
    }
    //以太网报文处理
    public void asdu10() {
        if((rbuf[0]==(byte)(0x90&0xFF))&&(rbuf[1]==(byte)(0xEB&0xFF))) {  //报文标识符正确
            int m = rbuf[10] & 0xFF;
            int adr = (int) adrtable.get(m);
            if (adr < 40) sn[adr] = 0;
            bw = 0;
            if (len > 28) {  //数据量小的数据包是心跳包，不解析
                int n1 = (rbuf[2] & 0xFF) + 8;
                bw = 1;
                for (int i = 0; i < (n1 - 28); i++) buf[i] = rbuf[28 + i];
                gin(adr);
                if (len > n1) {       //数据包包含第2帧数据
                    if ((rbuf[n1] == 0x90) && (rbuf[n1 + 1] == 0xEB)) {
                        bw = 2;
                        int n2 = (rbuf[n1 + 2] & 0xFF) + 8;
                        for (int i = 0; i < (n2 - 28); i++) buf[i] = rbuf[n1 + 28 + i];
                        gin(adr);
                        if (len > (n1 + n2)) {   //数据包包含第3帧数据
                            if ((rbuf[n1 + n2] == 0x90) && (rbuf[n1 + n2 + 1] == 0xEB)) {
                                bw = 3;
                                int n3 = (rbuf[n1 + n2 + 2] & 0xFF) + 8;
                                for (int i = 0; i < (n3 - 28); i++) buf[i] = rbuf[n1 + n2 + 28 + i];
                                gin(adr);
                            }
                        }
                    }
                }
            }
        }
    }
    // COM1读取数据的线程
    private class ReadThread1 extends Thread {
        @Override
        public void run() {
            super.run();
            while(true){
                try {
                    int n = serialPort.read(rbuf1,32);
                    if(n > 10) {
                        if((rbuf1[0]==(byte)0x05)&&(rbuf1[1]==(byte)0x03)) {  //直流电源
                            for (int i=0;i<10;i++) Reg[i+10]=rbuf1[i+3];
                        }
                        if((rbuf1[0]==(byte)0x14)&&(rbuf1[1]==(byte)0x02)) {  //小电流接地选线
                            for (int i=0;i<3;i++) Reg[i]=rbuf1[i+3];
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
    // COM2读取数据的线程
    private class ReadThread2 extends Thread {
        @Override
        public void run() {
            super.run();
            while(true){
                try {
                    byte[] mbuf =new byte[32];
                    int n1 = serialPort2.read(mbuf,32);
                    for(int i=0;i<n1;i++) rbuf2[i]=mbuf[i];
                    if(n1>10){
                        try {    //每次接收16字节，超过16字节时，延时100ms再次接收剩余数据
                            sleep(100);
                        } catch (InterruptedException e) {
                        }
                        int n2 = serialPort2.read(mbuf,32);
                        for(int i=0;i<n2;i++) rbuf2[i+n1]=mbuf[i];
                        int fn=0;
                        for(int i=0;i<5;i++)
                        {
                            if(rbuf2[i]==(byte)0x68)
                            {
                                fn=i;
                                break;
                            }
                        }
                        int CS=0;
                        int mn = 10 + rbuf2[9+fn]+fn;
                        for(int i=fn;i<mn;i++) CS=CS+rbuf2[i]&0xFF;
                        if((rbuf2[mn]&0xFF)==(CS&0xFF)) {
                            if(tn2<hmax) {     //有功电量
                                int i=20+8*tn2;
                                Reg[i]= (byte) ((rbuf2[15+fn]&0xFF)-0x33);
                                Reg[i+1]= (byte) ((rbuf2[14+fn]&0xFF)-0x33);
                                Reg[i+2]= (byte) ((rbuf2[13+fn]&0xFF)-0x33);
                                Reg[i+3]= (byte) ((rbuf2[12+fn]&0xFF)-0x33);
                            }else {  //无功电量
                                int i=24+8*(tn2-hmax);
                                Reg[i]= (byte) ((rbuf2[15+fn]&0xFF)-0x33);
                                Reg[i+1]= (byte) ((rbuf2[14+fn]&0xFF)-0x33);
                                Reg[i+2]= (byte) ((rbuf2[13+fn]&0xFF)-0x33);
                                Reg[i+3]= (byte) ((rbuf2[12+fn]&0xFF)-0x33);
                            }
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
   //读取电度表数据
    public void DLT645(int nd,int addrd)
    {
        byte[] tbuf2 = new byte[14];
        tbuf2[0]=(byte)0x68;
        for(int i=0;i<6;i++) tbuf2[i+1]=mymt[6*nd+i];
        tbuf2[7]=(byte)0x68;
        tbuf2[8]=(byte)1;
        tbuf2[9]=(byte)2;
        tbuf2[10]=(byte) ((addrd&0xFF)+0x33);  //地址低字节在前
        tbuf2[11]=(byte) (((addrd>>8)&0xFF)+0x33);   //高字节在后
        int CS=0;
        for(int i=0;i<12;i++) CS=CS+tbuf2[i]&0xFF;
        tbuf2[12]=(byte)(CS&0xFF);  //校验和
        tbuf2[13]=(byte)0x16;  //结束符
        serialPort2.write(tbuf2,14); //发送数据
    }
}
